home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 5
/
Apprentice-Release5.iso
/
Source Code
/
C
/
Applications
/
Python 1.3.3
/
Python 133 SRC
/
Extensions
/
img
/
imgpbmmodule.c
< prev
next >
Wrap
Text File
|
1995-12-21
|
13KB
|
545 lines
/***********************************************************
Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Amsterdam, The Netherlands.
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the names of Stichting Mathematisch
Centrum or CWI not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior permission.
STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
******************************************************************/
#include "Python.h"
#include "import.h"
#include "pbm.h"
/* The image formats we support */
static PyObject *format_pbm, *format_choices;
extern PyObject *getimgformat(); /* Get format by name */
/*
** Since PBMPLUS error handling is abysmal (print message, exit),
** there is a modified version that has (slightly) better error
** handling. Contact jack@cwi.nl if you want it. Define PBMNEWERROR
** if you have the modified pbmplus.
**
** If you don't have it the first pbm error will abort you python
** program.
*/
#define PBMNEWERROR
#ifndef PBMNEWERROR
#define PBM_END
#define PBM_START if (0) {
#define PBM_ENDSTART }
#else
#include <setjmp.h>
jmp_buf pbmerrenv;
char pbmerrstr[1000];
#define PBM_END pm_setmsghandler(0); pm_setexithandler(0);
#define PBM_START if ( setjmp(pbmerrenv) != 0 ) { \
PyErr_SetString(errobject, pbmerrstr); \
*pbmerrstr = '\0'; \
PBM_END
#define PBM_ENDSTART return 0; \
} \
pm_setmsghandler(my_pmerr); \
pm_setexithandler(my_pmexit);
static void
my_pmerr(str)
char *str;
{
strncpy(pbmerrstr, str, 999);
}
static void
my_pmexit()
{
longjmp(pbmerrenv, 1);
}
#endif /* PBMNEWERROR */
/* Pbm objects */
typedef struct {
PyObject_HEAD
PyObject *dict; /* Attributes dictionary */
int is_reader; /* TRUE if this is a reader */
char *filename; /* filename of the image file */
FILE *filep;
int format;
} pbmobject;
static PyObject *errobject;
staticforward PyTypeObject Pbmtype;
#define is_pbmobject(v) ((v)->ob_type == &Pbmtype)
static char doc_pbm[] = "This object reads/writes PBM files\n"
"The 'width', 'height' and 'format' attributes describe the picture\n"
"For writers, setting 'forceplain' creates an ASCII PBM file.";
/* Routine to easily obtain C data from the dict python data */
int
pbmselfattr(self, name, fmt, ptr, wanterr)
pbmobject *self;
char *name;
char *fmt;
void *ptr;
int wanterr;
{
PyObject *obj;
char errbuf[100];
obj = PyDict_GetItemString(self->dict, name);
if ( obj == NULL ) {
if ( wanterr ) {
sprintf(errbuf, "Required attribute '%s' not set", name);
PyErr_SetString(errobject, errbuf);
return 0;
} else {
PyErr_Clear();
return 0;
}
}
if ( !PyArg_Parse(obj, fmt, ptr) ) {
if ( !wanterr )
PyErr_Clear();
return 0;
}
return 1;
}
/* Routine to easily insert integer into dictionary */
pbmsetintattr(self, name, value)
pbmobject *self;
char *name;
int value;
{
PyObject *obj;
int rv;
obj = PyInt_FromLong(value);
rv = PyDict_SetItemString(self->dict, name, obj);
Py_DECREF(obj);
return rv;
}
static pbmobject *
newpbmobject()
{
pbmobject *xp;
xp = PyObject_NEW(pbmobject, &Pbmtype);
if (xp == NULL)
return NULL;
xp->dict = PyDict_New();
xp->filename = NULL;
xp->filep = NULL;
return xp;
}
static int
initpbmreader(self, name)
pbmobject *self;
char *name;
{
char *name_copy;
int cols, rows;
if( (name_copy=malloc(strlen(name)+1)) == NULL ) {
PyErr_NoMemory();
return 0;
}
strcpy(name_copy, name);
self->filename = name_copy;
self->is_reader = 1;
if ((self->filep = fopen(self->filename, "rb")) == NULL ) {
PyErr_SetFromErrno(PyExc_IOError);
return 0;
}
PBM_START
fclose(self->filep);
self->filep = 0;
return 0;
PBM_ENDSTART
pbm_readpbminit(self->filep, &cols, &rows, &self->format);
PBM_END
pbmsetintattr(self, "width", cols);
pbmsetintattr(self, "height", rows);
PyDict_SetItemString(self->dict, "format", format_pbm);
PyDict_SetItemString(self->dict, "format_choices", format_choices);
if ( PyErr_Occurred() )
return 0;
return 1;
}
static int
initpbmwriter(self, name)
pbmobject *self;
char *name;
{
char *name_copy;
if( (name_copy=malloc(strlen(name)+1)) == NULL ) {
PyErr_NoMemory();
return 0;
}
strcpy(name_copy, name);
self->filename = name_copy;
self->filep = NULL;
self->is_reader = 0;
PyDict_SetItemString(self->dict, "format", format_pbm);
PyDict_SetItemString(self->dict, "format_choices", format_choices);
if( PyErr_Occurred())
return 0;
return 1;
}
/* Pbm methods */
static void
pbm_dealloc(xp)
pbmobject *xp;
{
Py_XDECREF(xp->dict);
if( xp->filename )
free(xp->filename);
if( xp->filep )
fclose(xp->filep);
PyMem_DEL(xp);
}
static char doc_read[] = "Read the actual data, returns a string";
static PyObject *
pbm_read(self, args)
pbmobject *self;
PyObject *args;
{
int i, w, h, rowlen;
PyObject *rv;
char *datap;
bit *pixelrow;
PyObject *fmt;
if (!PyArg_ParseTuple(args,""))
return NULL;
if (!self->is_reader) {
PyErr_SetString(errobject, "Cannot read() from writer object");
return NULL;
}
/* XXXX Read data and return it */
/* XXXX Get args from self->dict and write the data */
if ( !pbmselfattr(self, "width", "i", &w, 1) ||
!pbmselfattr(self, "height", "i", &h, 1) ||
!pbmselfattr(self, "format", "O", &fmt, 1) )
return NULL;
if ( fmt != format_pbm ) {
PyErr_SetString(errobject, "Unsupported image format");
return NULL;
}
pixelrow = 0;
rv = 0;
PBM_START
if ( pixelrow )
pbm_freerow(pixelrow);
if ( rv )
Py_DECREF(rv);
return NULL;
PBM_ENDSTART
rowlen = w;
pixelrow=pbm_allocrow(w);
if ( (rv=PyString_FromStringAndSize(0, rowlen*h)) == NULL ) {
pbm_freerow(pixelrow);
return NULL;
}
datap = PyString_AsString(rv);
while( h > 0 ) {
pbm_readpbmrow(self->filep, pixelrow, w, self->format);
for(i=0; i<w; i++)
datap[i] = pixelrow[i];
datap += rowlen;
h -= 1;
}
PBM_END
pbm_freerow(pixelrow);
return rv;
}
static char doc_write[] = "Write (string) data to the PBM file";
static PyObject *
pbm_write(self, args)
pbmobject *self;
PyObject *args;
{
unsigned char *data;
int datalen;
int i, w, h, rowlen;
PyObject *fmt;
bit *pixelrow;
int forceplain;
FILE *filep;
if (!PyArg_ParseTuple(args, "s#", &data, &datalen))
return NULL;
if (self->is_reader) {
PyErr_SetString(errobject, "Cannot write() to reader object");
return NULL;
}
/* XXXX Get args from self->dict and write the data */
if ( !pbmselfattr(self, "width", "i", &w, 1) ||
!pbmselfattr(self, "height", "i", &h, 1) ||
!pbmselfattr(self, "format", "O", &fmt, 1) )
return NULL;
forceplain = 0;
pbmselfattr(self, "forceplain", "i", &forceplain, 0);
rowlen = w;
if ( fmt != format_pbm ) {
PyErr_SetString(errobject, "Unsupported image format");
return NULL;
}
if( rowlen*h != datalen ) {
PyErr_SetString(errobject, "Incorrect datasize");
return NULL;
}
if ((filep = fopen(self->filename, forceplain?"w":"wb")) == NULL) {
PyErr_SetFromErrno(PyExc_IOError);
return 0;
}
#ifdef macintosh
setfiletype(self->filename, '????', 'PPBM');
#endif
pixelrow = 0;
PBM_START
if ( pixelrow )
pbm_freerow(pixelrow);
fclose(filep);
return NULL;
PBM_ENDSTART
pixelrow=pbm_allocrow(w);
pbm_writepbminit(filep, w, h, forceplain);
while( h > 0 ) {
for(i=0; i<w; i++)
pixelrow[i] = data[i];
pbm_writepbmrow(filep, pixelrow, w, forceplain);
data += rowlen;
h -= 1;
}
PBM_END
pbm_freerow(pixelrow);
if (fclose(filep) != 0) {
PyErr_SetFromErrno(PyExc_IOError);
return NULL;
}
Py_INCREF(Py_None);
return Py_None;
}
static struct PyMethodDef pbm_methods[] = {
{"read", (PyCFunction)pbm_read, 1, doc_read},
{"write", (PyCFunction)pbm_write, 1, doc_write},
{NULL, NULL} /* sentinel */
};
static PyObject *
pbm_getattr(xp, name)
pbmobject *xp;
char *name;
{
PyObject *v;
if (xp->dict != NULL) {
if ( strcmp(name, "__dict__") == 0 ) {
Py_INCREF(xp->dict);
return xp->dict;
}
if ( strcmp(name, "__doc__") == 0 ) {
return PyString_FromString(doc_pbm);
}
v = PyDict_GetItemString(xp->dict, name);
if (v != NULL) {
Py_INCREF(v);
return v;
}
}
return Py_FindMethod(pbm_methods, (PyObject *)xp, name);
}
static int
pbm_setattr(xp, name, v)
pbmobject *xp;
char *name;
PyObject *v;
{
if (xp->dict == NULL) {
xp->dict = PyDict_New();
if (xp->dict == NULL)
return -1;
}
if (v == NULL) {
int rv = PyDict_DelItemString(xp->dict, name);
if (rv < 0)
PyErr_SetString(PyExc_AttributeError,
"delete non-existing imgpbm attribute");
return rv;
}
else
return PyDict_SetItemString(xp->dict, name, v);
}
static PyTypeObject Pbmtype = {
PyObject_HEAD_INIT(&PyType_Type)
0, /*ob_size*/
"imgpbm", /*tp_name*/
sizeof(pbmobject), /*tp_basicsize*/
0, /*tp_itemsize*/
/* methods */
(destructor)pbm_dealloc, /*tp_dealloc*/
0, /*tp_print*/
(getattrfunc)pbm_getattr, /*tp_getattr*/
(setattrfunc)pbm_setattr, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash*/
};
static char doc_newreader[] =
"Return an object that reads the PBM/PBM file passed as argument";
static PyObject *
pbm_newreader(self, args)
PyObject *self;
PyObject *args;
{
char *filename;
pbmobject *obj;
if (!PyArg_ParseTuple(args, "s", &filename))
return NULL;
if ((obj = newpbmobject()) == NULL)
return NULL;
if ( !initpbmreader(obj, filename) ) {
pbm_dealloc(obj);
return NULL;
}
return (PyObject *)obj;
}
static char doc_newwriter[] =
"Return an object that writes the PBM file passed as argument";
static PyObject *
pbm_newwriter(self, args)
PyObject *self;
PyObject *args;
{
char *filename;
pbmobject *obj;
if (!PyArg_ParseTuple(args, "s", &filename))
return NULL;
if ((obj = newpbmobject()) == NULL)
return NULL;
if ( !initpbmwriter(obj, filename) ) {
pbm_dealloc(obj);
return NULL;
}
return (PyObject *)obj;
}
/* List of functions defined in the module */
static struct PyMethodDef pbm_module_methods[] = {
{"reader", pbm_newreader, 1, doc_newreader},
{"writer", pbm_newwriter, 1, doc_newwriter},
{NULL, NULL} /* sentinel */
};
/* Initialization function for the module (*must* be called initimgpbm) */
static char doc_imgpbm[] =
"Module that reads images from PBM files writes them too.";
void
initimgpbm()
{
PyObject *m, *d, *x, *formatmodule, *formatdict;
/* Create the module and add the functions */
m = Py_InitModule("imgpbm", pbm_module_methods);
/* Add some symbolic constants to the module */
d = PyModule_GetDict(m);
errobject = PyString_FromString("imgpbm.error");
PyDict_SetItemString(d, "error", errobject);
x = PyString_FromString(doc_imgpbm);
PyDict_SetItemString(d, "__doc__", x);
/* Get supported formats */
if ((formatmodule = PyImport_ImportModule("imgformat")) == NULL)
Py_FatalError("imgpbm depends on imgformat");
if ((formatdict = PyModule_GetDict(formatmodule)) == NULL)
Py_FatalError("imgformat has no dict");
format_pbm = PyDict_GetItemString(formatdict,"pbmbitmap");
format_choices = Py_BuildValue("(O)", format_pbm);
/* Initialize pbmplus */
{
int pbm_argc;
static char *pbm_arglist[] = { "pbmplus", 0};
char **pbm_argv;
pbm_argc = 1;
pbm_argv = pbm_arglist;
PBM_START /* { */
Py_FatalError("pbmplus initialization error");
} /* PBM_ENDSTART won't work here, it has return NULL */
pbm_init(&pbm_argc, pbm_argv);
PBM_END
}
/* Check for errors */
if (PyErr_Occurred())
Py_FatalError("can't initialize module imgpbm");
}